package com.taysear.bus;

import java.util.HashMap;

import com.taysear.bus.util.Constants;
import com.taysear.bus.util.Results;
import com.taysear.bus.util.Util;
import com.taysear.bus.util.tpt.Captcha;
import com.taysear.dbservice.DbServicesPrx;
import com.taysear.dbservice.ServiceParameter;
import com.taysear.dbservice.ServiceResult;
import com.taysear.domain.Country;
import com.taysear.domain.Currency;
import com.taysear.domain.Employee;
import com.taysear.domain.Station;
import com.taysear.domain.User;
import com.vaadin.Application;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.Runo;

/**
 * <code>LoginScreen</code> is used to create the login form of the application.
 * 
 * @author Abdullahi
 */
@SuppressWarnings("serial")
public class LoginScreen extends VerticalLayout {

	private Captcha captcha = null;
	HorizontalLayout captchaLayout = new HorizontalLayout();
	TextField captchaResult = new TextField("Captcha result");
	private int wrongPasswordTrials = 1;
	
	public LoginScreen() {
		setSizeFull();
		
		Component loginPanel = getLoginForm();
		
		addComponent(loginPanel);
		setComponentAlignment(loginPanel, Alignment.MIDDLE_CENTER);

	}
	
	@Override
	public void attach() {
		super.attach();
		captcha = new Captcha();
		
		captchaLayout.setSpacing(true);
		captchaLayout.addComponent(captcha);
		captchaLayout.addComponent(getGenerateCaptchaCodeButton());
		
	}
	
	private Button getGenerateCaptchaCodeButton() {
		Button button = new Button("Generate captcha");
		button.addStyleName("greenButton");
		button.setDisableOnClick(true);
		button.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	captcha.generateCaptchaCode(5);
		    	event.getButton().setEnabled(true);
		    }
		});
		
		return button;
	}
	
	private Component getLoginForm() {
		Panel panel = new Panel("Login");
		panel.addStyleName(Runo.PANEL_LIGHT);
		
		final Form form = new Form();
		
		TextField userName = new TextField("Username");
		userName.focus();
		userName.setRequired(true);
		userName.setRequiredError("This field is required");
		userName.setValue("admin");
		form.addField("username", userName);
		
		PasswordField password = new PasswordField("Password");
		password.setRequired(true);
		password.setRequiredError("This field is required");
		password.setValue("admin");
		form.addField("password", password);
		
		captchaLayout.setVisible(false);
		form.getLayout().addComponent(captchaLayout);
		
		captchaResult.setVisible(false);
		form.addField("captchaResult", captchaResult);
		
		Button login = getLoginButton(form);
		form.addField("", login);
		
		return form;
	}
	
	/**
	 * Get a button that logs the user in.
	 * 
	 * @return Button
	 */
	private Button getLoginButton(final Form form) {
		Button button = new Button("Login");
		button.addStyleName("blueButton");
		button.setDisableOnClick(true);
		button.addListener(new Button.ClickListener() {
		    @Override
		    public void buttonClick(ClickEvent event) {
		    	BusApplication app = (BusApplication) getApplication();
		    	if(form.isValid()) {
		    		String captchResultString = form.getField("captchaResult").getValue().toString();
		    		String captchaCode = captcha.getCaptchaCode();
		    		if(wrongPasswordTrials <= 3 | (wrongPasswordTrials > 3 && captchResultString.equalsIgnoreCase(captchaCode))) {
			    		ServiceParameter sp = new ServiceParameter(new HashMap<String, String>());
			    		sp.param.put("username", form.getField("username").toString());
			    		sp.param.put("password", User.hash(form.getField("password").toString()));
			    		
			    		DbServicesPrx dbServicesPrx = app.getDbServiceProxy();
			    		ServiceResult sr = dbServicesPrx.login(sp);
			    		if(sr.status) {
			    			Results r1 = Util.getObjectsFromXmlResult(sr.param.get("RECORDS"), User.class);
			    			Results r2 = Util.getObjectsFromXmlResult(sr.param.get("EMPLOYEE"), Employee.class);
			    			Results r3 = Util.getObjectsFromXmlResult(sr.param.get("COUNTRY"), Country.class);
			    			Results r4 = Util.getObjectsFromXmlResult(sr.param.get("CURRENCY"), Currency.class);
			    			
			    			User user = (User) r1.getRows().iterator().next();
			    			
			    			Employee employee = (Employee) r2.getRows().iterator().next();
			    			
			    			Station station = new Station();
			    			Country country = (Country) r3.getRows().iterator().next();
			    			
			    			country.setCurrency((Currency) r4.getRows().iterator().next());
			    			station.setCountry(country);
			    			employee.setStation(station);
			    			
			    			user.setEmployee(employee);
			    			
			    			AppData.setUser(user);
			    			
				    		MainLayout mainLayout = app.getMainLayout();
				    		mainLayout.loadMenuAndUserInfo();
			    		} else {
			    			if(wrongPasswordTrials == 3) {
			    				captchaLayout.setVisible(true);
			    				captchaResult.setVisible(true);
			    				captchaResult.setRequired(true);
			    				captchaResult.setRequiredError("This field is required");
			    				
			    				wrongPasswordTrials += 1;
			    			} else if(wrongPasswordTrials <= 2) {
				    			wrongPasswordTrials += 1;
			    			}
			    			app.showErrorNotification("Invalid username / password");
			    			event.getButton().setEnabled(true);
			    		}
		    		} else {
		    			app.showErrorNotification("Invalid captcha code");
		    			event.getButton().setEnabled(true);
		    		}
		    	} else {
		    		app.showErrorNotification(Constants.ME_FORM_FIELDS_REQUIRED);
		    		event.getButton().setEnabled(true);
		    	}
		    } 
		});
		return button;
	}
}
